home *** CD-ROM | disk | FTP | other *** search
/ ftp.mactech.com 2010 / ftp.mactech.com.tar / ftp.mactech.com / challenge / 12.11-Nov96 / 12.11Challenge.sit.hqx / 12.11 Challenge / JavaMiniVM.c < prev   
Text File  |  1996-09-01  |  32KB  |  1,794 lines

  1. /* Byte-Code Interpreter By Xan Gregg September 1996
  2.  
  3. The core of the interpreter is written in mostly PowerPC
  4. assember, and the parsing of the tables is done in C
  5. before interpreting begins.  I create tables of relevant
  6. data for constants, fields, and methods.  The constants
  7. data is just the address of the Java constant_pool data for
  8. that index.  For fields and methods I allocate structs
  9. with the useful data and insert a pointer to the struct
  10. into the field's or method's constant_pool entry.
  11.  
  12. So, for some up-front overhead and memory usage (16 bytes
  13. per field or method), the interpreter has less work to
  14. do when dealing with a field or method.
  15.  
  16. String objects are pointers to the constant_pool
  17. payload, just as the provided test code expects.
  18.  
  19. Objects in general are greatly simplified because of the
  20. one class limitation.  No type information is stored with
  21. any object in the heap.
  22.  
  23. Of the 10M of provided heapSpace, I use 512K for the Java
  24. heap, 512K for the Java stacks (data and return), and
  25. the rest is available for the constant, field, and method
  26. tables, which will consume less that 20 * NumConstants
  27. bytes.
  28.  
  29. The heap size and stack size can be set by the macros
  30. HEAP_K and STACK_K below.  No garbage collection is
  31. performed on the heap, so if there is lots of object
  32. creation, a larger heap may be needed.
  33.  
  34. The VM has two stacks, a data stack and a return stack.
  35. The data stack grows up from the start of the stack space,
  36. and the return stack grows down from the end of the
  37. stack space.  The data stack is used for parameters and
  38. normal Java stack operations.  The return stack is used
  39. method nesting.  Each call makes a three-entry stack frame
  40. consisting of the return address, frame pointer (start of
  41. locals), and tsBase (the method base for use by tableswitch
  42. and lookupswitch).
  43.  
  44. Having separate stacks made the parameter passing easier,
  45. but now I realize that with some extra work, I could have
  46. just put the return frame into added local variables.
  47.  
  48. The Top-Of-Stack is kept in a register.  This requires
  49. a little handshaking when the interpreter calls another
  50. function, which doesn't have access to the TOS register.
  51.  
  52. The core of the interpreter is in the assembly routine,
  53. StartVM.  Its main loop fetches and dispatches opcodes,
  54. as expected.  It includes a table with a 32-byte entry
  55. for each opcode (up through 209).  An entry consists
  56. of code to implement the opcode.  Most of them fit in
  57. 32-bytes, and any extra space is used to prime the
  58. dispatch loop.
  59.  
  60. Opcodes that take more than 7 instructions to implement
  61. can spill over to code outside of the table.  Opcodes
  62. that are particularly complex (like multianewarray)
  63. are implemented with C functions.
  64.  
  65.  
  66. Limitations:
  67. I try to safely ignore operations involving long, double,
  68. and float operands by treating these types as taking 0
  69. bytes each.  Most instructions become a NOP, and others
  70. are very simple (i2d become a POP).  However, I have
  71. realized one flaw to this system:  The untyped instructions
  72. (like DUP) may try to operate on the unsupported types.
  73. It's too late to fix now, but since the challenge will try
  74. to avoid unsupported types, it's unlikely the stack
  75. manipulation of them will be needed.
  76.  
  77. Future:
  78. With the PowerPC code done for each opcode, it would
  79. not be too tough to make a compiler that would string
  80. together the PowerPC code for each opcode in each method.
  81. */
  82.  
  83. #include <stdio.h>
  84. #include <stdlib.h>
  85. #include <string.h>
  86.  
  87. // Java types
  88. typedef signed char s1;
  89. typedef signed short s2;
  90. typedef signed long s4;
  91. typedef unsigned char u1;
  92. typedef unsigned short u2;
  93. typedef unsigned long u4;
  94.  
  95. // Set these if necessary
  96. #define HEAP_K    512
  97. #define STACK_K    512
  98.  
  99. // the CONSTANT_ id's
  100. enum {C_Utf8 = 1, C_Unicode, C_Integer, C_Float, C_Long,
  101.         C_Double, C_Class, C_String, C_Fieldref,
  102.         C_Methodref, C_InterfaceMethodref, C_NameAndType};
  103.  
  104. const u2 ACC_STATIC = 0x0008;
  105.  
  106. // The contents of my tables
  107. typedef u1 *ConstantData;
  108.  
  109. typedef struct
  110. {
  111.     u2        *fieldInfoP;
  112.     long    offset;        // in bytes
  113.     long    size;        // in bytes
  114.     u1        *type;        // ptr to sig constant
  115. } FieldData;
  116.  
  117. typedef struct
  118. {
  119.     u2        *methodInfoP;
  120.     u2        *codeAttrP;
  121.     u1        *codeP;
  122.     u4        paramCount;        // in bytes
  123. } MethodData;
  124.  
  125. // prototypes
  126. void JavaMiniVM(void *constant_pool, void *fields,
  127.     void *methods, void *classFile,
  128.     long methodToExecute, void *heapSpace,void *returnStack);
  129.  
  130. static short IndexConstants(void *constants,
  131.                                 ConstantData *indexArray);
  132. static short IndexFields(void *fields);
  133. static short IndexMethods(void *methods);
  134. static void CreateAndPush(void);
  135. static void AllocateStaticFields(void);
  136. static void ResolveFields(void);
  137. static void ResolveMethods(void);
  138. static void CountParams(MethodData *methodP);
  139. asm static long StartVM(register MethodData *methodP);
  140. static void PushConstant(long n);
  141. static u1 *TableSwitch(u1 *ip, long tsBase, long n);
  142. static u1 *LookupSwitch(u1 *ip, long tsBase, long key);
  143. static long GetNewArray(long type, long size);
  144. static long GetANewArray(long size);
  145. static void PushMultiANewArray(long classIndex,
  146.                                 long numDimensions);
  147.  
  148. // globals
  149. static long            NumMethods;
  150. static long            NumFields;
  151. static long            NumConstants;
  152. static MethodData    *Methods;
  153. static FieldData    *Fields;
  154. static ConstantData    *Constants;
  155. static long            *FP;    // frame pointer
  156. static long            *SP;    // stack pointer
  157. static long            *S0;    // stack base
  158. static long            *RP;    // return stack pointer
  159. static long            *R0;    // return stack base
  160. static long            *HP;    // heap pointer
  161. static long            *H0;    // heap base
  162. static long            TotalStatic;    // in bytes
  163. static long            TotalNonStatic;    // in bytes
  164. static long            LastField;
  165. static long            LastMethod;
  166.  
  167. /* java types
  168. typedef struct
  169. {
  170. 0    u2    attribute_name;
  171. 2    u4    attribute_length;
  172. 6    u1    info[1];
  173. } attribute_info;
  174.  
  175. typedef struct
  176. {
  177. 0    u2    access_flags;
  178. 2    u2    name_index;
  179. 4    u2    signature_index;
  180. 6    u2    attribute_count;
  181. 8    attribute_info    attributes[1];
  182. } field_info;
  183.  
  184. typedef struct
  185. {
  186. 0    u2    access_flags;
  187. 2    u2    name_index;
  188. 4    u2    signature_index;
  189. 6    u2    attribute_count;
  190. 8    attribute_info    attributes[1];
  191. } method_info;
  192.  
  193. typedef struct
  194. {
  195. 0    u1    tag;
  196. 1    u2    length;
  197. 3    u1    bytes[1];
  198. } CONSTANT_Utf8_info
  199. */
  200.  
  201. #define PUSH(a)        *SP++ = (a)
  202.  
  203. #define MethodIsStatic(n)    \
  204.     ((*Methods[n].methodInfoP & ACC_STATIC) != 0)
  205.  
  206. void JavaMiniVM(void *constant_pool, void *fields,
  207.     void *methods, void *classFile,
  208.     long methodToExecute, void *heapSpace,void *returnStack)
  209. {    
  210.     //allocate java heap
  211.     H0 = (long *) heapSpace;
  212.     HP = H0;
  213.     // allocate java stack (stack grows up in memory)
  214.     S0 = H0 + HEAP_K * 256L;    // 256 longs = 1K
  215.     SP = S0;
  216.     
  217.     // return stack based at end of stack space (grows down)
  218.     R0 = S0 + STACK_K * 256L;    // 256 longs = 1K
  219.     RP = R0;
  220.     
  221.     Constants = (ConstantData *) R0;
  222.     NumConstants = IndexConstants(constant_pool, Constants);
  223.     
  224.     Fields = (FieldData *) (Constants + NumConstants);
  225.     NumFields = IndexFields(fields);
  226.     Methods = (MethodData *) (Fields + NumFields);
  227.     NumMethods = IndexMethods(methods);
  228.     
  229.     ResolveFields();
  230.     ResolveMethods();
  231.     AllocateStaticFields();
  232.     if (!MethodIsStatic(methodToExecute))
  233.         CreateAndPush();    // so it needs an obj
  234.     *(long *) returnStack =
  235.             StartVM(&Methods[methodToExecute]);
  236.     
  237. }
  238.  
  239.  
  240. // create on index into the constant_pool
  241. static short IndexConstants(void *constants,
  242.                                 ConstantData *indexArray)
  243. {
  244.     short    n, i;
  245.     u1        *p;
  246.     
  247.     // list is preceded by length
  248.     n = * ((u2 *) constants - 1);
  249.     p = (u1 *) constants;
  250.     LastField = 0;
  251.     LastMethod = 0;
  252.     for (i = 1; i < n; i++)
  253.     {
  254.         indexArray[i] = p;
  255.         switch (*p)
  256.         {
  257.             case C_Utf8:    p += 3 + *(u2*)(p+1); break;
  258.             case C_Unicode:    p += 3 + *(u2*)(p+1); break;
  259.             case C_Integer:    p += 5; break;
  260.             case C_Float:    p += 5; break;
  261.             case C_Long:    p += 9; i += 1; break;
  262.             case C_Double:    p += 9; i += 1; break;
  263.             case C_Class:    p += 3; break;
  264.             case C_String:    p += 3; break;
  265.             case C_Fieldref: p += 5; LastField = i; break;
  266.             case C_Methodref: p += 5; LastMethod = i; break;
  267.             case C_InterfaceMethodref: p += 5; break;
  268.             case C_NameAndType:    p += 5; break;
  269.         }
  270.     }
  271.     indexArray[0] = p;    //useful for getting to 'this_class'
  272.     return n;
  273. }
  274.  
  275.  
  276. // Gather FieldData about each field
  277. static short IndexFields(void *fields)
  278. {
  279.     short    n, i;
  280.     u1        *p;
  281.     u1        *sigP;
  282.     u2        sigIndex;
  283.     FieldData    *fieldP;
  284.     u1        c;
  285.     long    staticOffset = 0;
  286.     long    memberOffset = 0;
  287.     
  288.     // list is preceded by length
  289.     n = * ((u2 *) fields - 1);
  290.     p = (u1 *) fields;
  291.     fieldP = Fields;
  292.     for (i = 0; i < n; i++)
  293.     {
  294.         short    count;    // attribute count
  295.         
  296.         fieldP->fieldInfoP = (u2 *) p;
  297.         sigIndex = *(u2 *) (p + 4);
  298.         sigP = Constants[sigIndex];
  299.         c = *(sigP + 3);
  300.         if (c == 'L' || c == 'D' || c == 'F')
  301.             fieldP->size = 0;
  302.         else
  303.             fieldP->size = 4;
  304.         fieldP->type = sigP;
  305.         if ((*fieldP->fieldInfoP & ACC_STATIC) != 0)
  306.         {
  307.             fieldP->offset = staticOffset;
  308.             staticOffset += fieldP->size;
  309.         }
  310.         else
  311.         {
  312.             fieldP->offset = memberOffset;
  313.             memberOffset += fieldP->size;
  314.         }
  315.         // skip attributes
  316.         count = * (u2 *) (p + 6);
  317.         p += 8;
  318.         while (count > 0)
  319.         {
  320.             count -= 1;
  321.             p += 6 + *(u4 *) (p+2);
  322.         }
  323.         fieldP += 1;
  324.     }
  325.     TotalStatic = staticOffset;
  326.     TotalNonStatic = memberOffset;
  327.     return n;
  328. }
  329.  
  330.  
  331. // Gather MethodData about each method
  332. static short IndexMethods(void *methods)
  333. {
  334.     short    n, i;
  335.     u1        *p;
  336.     MethodData    *methodP;
  337.     
  338.     // list is preceded by length
  339.     n = * ((u2 *) methods - 1);
  340.     p = (u1 *) methods;
  341.     methodP = Methods;
  342.     for (i = 0; i < n; i++)
  343.     {
  344.         short    count;    // attribute count
  345.         u2        nameIndex;
  346.         u1        *nameEntryP;
  347.         
  348.         methodP->methodInfoP = (u2 *) p;
  349.         CountParams(methodP);
  350.         count = * (u2 *) (p + 6);
  351.         p += 8;
  352.         while (count > 0)
  353.         {
  354.             nameIndex = * (u2 *) (p);
  355.             nameEntryP = Constants[nameIndex];
  356.             if (*(u2*)(nameEntryP + 1) == 4
  357.                     && *(long *) (nameEntryP + 3) == 'Code')
  358.             {    // this is the code attr
  359.                 methodP->codeAttrP = (u2 *) p;
  360.                 methodP->codeP = (u1 *) (p + 14);
  361.             }
  362.             count -= 1;
  363.             p += 6 + *(u4 *) (p+2);
  364.         }
  365.         methodP += 1;
  366.     }
  367.     return n;
  368. }
  369.  
  370.  
  371. // allocate 'this' and push a reference to it
  372. static void CreateAndPush(void)
  373. {
  374.     *SP = (long) HP;
  375.     SP ++;
  376.     // heap already initialized to zeros
  377.     HP = (long *) ((long) HP + TotalNonStatic);
  378. }
  379.  
  380.  
  381. static void AllocateStaticFields(void)
  382. {
  383.     // heap already initialized to zeros
  384.     HP = (long *) ((long) HP + TotalStatic);
  385. }
  386.  
  387. // Change the payload of CONSTANT_Fieldref items to be a
  388. // pointer into the FieldData array
  389. static void ResolveFields(void)
  390. {
  391.     short    i, j;
  392.     u1        *p;
  393.     u1        *q;
  394.     ConstantData    *constantP;
  395.     FieldData    *fieldP;
  396.     u2        nameTypeIndex;
  397.     u2        nameIndex;
  398.     
  399.     constantP = Constants+1;
  400.     for (i = 1; i <= LastField; i++)
  401.     {
  402.         p = *constantP++;
  403.         if (*p == C_Fieldref)
  404.         {
  405.             fieldP = Fields;
  406.             nameTypeIndex = *(u2*) (p + 3);
  407.             q = Constants[nameTypeIndex];
  408.             nameIndex = *(u2*) (q + 1);
  409.             for (j = 0; j < NumFields; j++)
  410.             {
  411.                 if (*(fieldP->fieldInfoP+1) == nameIndex)
  412.                 {    // found matching field ref, change it
  413.                     *(u4*) (p+1) = (u4) fieldP;
  414.                     break;
  415.                 }
  416.                 fieldP += 1;
  417.             }
  418.         }
  419.     }
  420. }
  421.  
  422.  
  423. // Change the payload of CONSTANT_Methodref items to be a
  424. // pointer into the MethodData array
  425. static void ResolveMethods(void)
  426. {
  427.     short    i, j;
  428.     u1        *p;
  429.     u1        *q;
  430.     ConstantData    *constantP;
  431.     MethodData    *methodP;
  432.     u2        nameTypeIndex;
  433.     u2        nameIndex;
  434.     u2        sigIndex;
  435.     
  436.     constantP = Constants+1;
  437.     for (i = 1; i <= LastMethod; i++)
  438.     {
  439.         p = *constantP++;
  440.         if (*p == C_Methodref)
  441.         {
  442.             methodP = Methods;
  443.             nameTypeIndex = *(u2*) (p + 3);
  444.             q = Constants[nameTypeIndex];
  445.             nameIndex = *(u2*) (q + 1);
  446.             sigIndex = *(u2*) (q + 3);
  447.             for (j = 0; j < NumMethods; j++)
  448.             {
  449.                 if (methodP->methodInfoP[1] == nameIndex
  450.                     && methodP->methodInfoP[2] == sigIndex)
  451.                 {    // found matching method ref, change it
  452.                     *(u4*) (p+1) = (u4) methodP;
  453.                     break;
  454.                 }
  455.                 methodP += 1;
  456.             }
  457.         }
  458.     }
  459. }
  460.  
  461.  
  462. static void CountParams(MethodData *methodP)
  463. {
  464.     long    sigIndex;
  465.     long    paramCount;
  466.     u1        *sigPtr;
  467.     u2        sigLength;
  468.     u1        ch;
  469.     
  470.     sigIndex = *(methodP->methodInfoP + 2);
  471.     sigPtr = Constants[sigIndex];
  472.     sigLength = * (u2 *) (sigPtr + 1);
  473.     sigPtr += 4;    // skip tag, length and '('
  474.     if ((*methodP->methodInfoP & ACC_STATIC) == 0)
  475.         paramCount = 4;    // implicit class object parameter
  476.     else
  477.         paramCount = 0;
  478.     while (1)
  479.     {
  480.         ch = *sigPtr;
  481.         if (ch == ')')
  482.             break;
  483.         paramCount += 4;
  484.         if (ch == 'D' || ch == 'J' || ch == 'F')
  485.             paramCount -= 4;    // these are 0-byte types
  486.         else if (ch == 'L')
  487.         {    // skip class name
  488.             while (*++sigPtr != ';')
  489.                 ;
  490.         }
  491.         else if (ch == '[')
  492.         {    // we don't care what it's an array of
  493.             while (*++sigPtr == '[')
  494.                 ;
  495.             if (*sigPtr == 'L')
  496.                 while (*++sigPtr != ';')
  497.                     ;
  498.         }
  499.         sigPtr += 1;
  500.     }
  501.     ch = *++sigPtr;
  502.     methodP->paramCount = paramCount;
  503. }
  504.  
  505.  
  506. #define slwi(r, n)                \
  507.     rlwinm    r, r, n, 0, 31-n;
  508.  
  509. #define times4(r)                \
  510.     rlwinm    r, r, 2, 0, 29;
  511.  
  512. // the number after 'used' indicates the number of
  513. // instructions used so far in this slot.
  514. #define used0                    \
  515.     lbz        opcode, 0(ip);        \
  516.     slwi(opcode, 5)                \
  517.     add        a, base, opcode;    \
  518.     mtctr    a;                    \
  519.     addi    ip, ip, 1;            \
  520.     bctr;                        \
  521.     nop; nop;
  522.     
  523. #define used1                    \
  524.     lbz        opcode, 0(ip);        \
  525.     slwi(opcode, 5)                \
  526.     add        a, base, opcode;    \
  527.     mtctr    a;                    \
  528.     addi    ip, ip, 1;            \
  529.     bctr;                        \
  530.     nop;
  531.     
  532. #define used2                    \
  533.     lbz        opcode, 0(ip);        \
  534.     slwi(opcode, 5)                \
  535.     add        a, base, opcode;    \
  536.     mtctr    a;                    \
  537.     addi    ip, ip, 1;            \
  538.     bctr;
  539.     
  540. #define used3                    \
  541.     lbz        opcode, 0(ip);        \
  542.     slwi(opcode, 5)                \
  543.     add        a, base, opcode;    \
  544.     mtctr    a;                    \
  545.     b        next4;
  546.     
  547. #define used4                    \
  548.     lbz        opcode, 0(ip);        \
  549.     slwi(opcode, 5)    \
  550.     add        a, base, opcode;    \
  551.     b        next3;
  552.     
  553. #define used5                    \
  554.     lbz        opcode, 0(ip);        \
  555.     slwi(opcode, 5)                \
  556.     b        next2;
  557.  
  558. #define used6                    \
  559.     lbz        opcode, 0(ip);        \
  560.     b        next1;
  561.  
  562. #define used7                    \
  563.     b        next0;
  564.  
  565. #define pushtos        \
  566.     stw        tos, 0(sp);    \
  567.     addi    sp, sp, 4;
  568.  
  569. #define poptos        \
  570.     lwzu    tos, -4(sp)
  571.  
  572. #define pushi(n)        \
  573.     stw        tos, 0(sp);    \
  574.     li        tos, n;        \
  575.     addi    sp, sp, 4;
  576.  
  577. #define pushr(r)        \
  578.     stw        tos, 0(sp);    \
  579.     mr        tos, r;        \
  580.     addi    sp, sp, 4;
  581.  
  582. // The initial return address points here.
  583. u1    ExitCode[1] = {203};
  584.  
  585. asm static long StartVM(register MethodData *methodP)
  586. {
  587.     register    long    *sp;
  588.     register    long    *rp;
  589.     register    long    *fp;
  590.     register    long    *h0;
  591.     register    long    *cp;    // Constants
  592.     register    u1        *ip;    // instruction ptr
  593.     register    u1        opcode;
  594.     register    long    tsBase;    // for tableswitch padding
  595.     register    long    a;
  596.     register    long    b;
  597.     register    long    c;
  598.     register    long    base;    // base of our opcode table
  599.     register    long    tos;
  600.     
  601.     fralloc
  602.     lwz        sp, SP
  603.     lwz        rp, RP
  604.     lwz        h0, H0
  605.     lwz        cp, Constants
  606.     lwz        a, ExitCode
  607.     stwu    a, -4(rp)    // push initial return ip
  608.     lwzu    tos, -4(sp)        // put TOS into a reg.
  609.     
  610.     // get address of opcode table
  611.     bl        nowhere
  612. nowhere:
  613.     mflr    base
  614.     // offset hard-coded since MW won't subtract labels
  615.     addi    base, base, 22*4    //table - nowhere
  616.     
  617. start_method:
  618.     stwu    fp, -4(rp)
  619.  
  620.     pushtos    // put tos (last param) in memory
  621.     mr        fp, sp
  622.     // FP points to first parameter
  623.     lwz        a, methodP->paramCount
  624.     subf    fp, a, fp
  625.     // allocate space for locals
  626.     lwz        b, methodP->codeAttrP
  627.     lhz        c, 8(b)        // max locals
  628.     times4(c)
  629.     subf    c, a, c
  630.     add        sp, sp, c
  631.     // init ip
  632.     lwz        ip, methodP->codeP
  633.     // init tsBase
  634.     andi.    tsBase, ip, 3
  635.     stwu    tsBase, -4(rp)
  636.     
  637. next0:
  638.     lbz        opcode, 0(ip)
  639. next1:
  640.     slwi(opcode, 5)
  641. next2:
  642.     add        a, base, opcode
  643. next3:
  644.     mtctr    a
  645. next4:
  646.     addi    ip, ip, 1
  647.     bctr
  648.     
  649. table:
  650.     // 0 nop
  651.     used0
  652.     // 1 aconst_null
  653.     pushi(0)
  654.     used3
  655.     // 2 iconst_m1
  656.     pushi(-1)
  657.     used3
  658.     // 3 iconst_0
  659.     pushi(0)
  660.     used3
  661.     // 4 iconst_1
  662.     pushi(1)
  663.     used3
  664.     // 5 iconst_2
  665.     pushi(2)
  666.     used3
  667.     // 6 iconst_3
  668.     pushi(3)
  669.     used3
  670.     // 7 iconst_4
  671.     pushi(4)
  672.     used3
  673.     // 8 iconst_5
  674.     pushi(5)
  675.     used3
  676.     // 9 lconst_0
  677.     used0
  678.     // 10 lconst_1
  679.     used0
  680.     // 11 fconst_0
  681.     used0
  682.     // 12 fconst_1
  683.     used0
  684.     // 13 fconst_2
  685.     used0
  686.     // 14 dconst_0
  687.     used0
  688.     // 15 dconst_1
  689.     used0
  690.     // 16 bipush
  691.     lbz        a, 0(ip)
  692.     extsb    a, a
  693.     addi    ip, ip, 1
  694.     pushr(a)
  695.     used6
  696.     // 17 sipush
  697.     lha        a, 0(ip)
  698.     addi    ip, ip, 2
  699.     pushr(a)
  700.     used5
  701.     // 18 ldc1
  702.     lbz        r3, 0(ip)
  703.     addi    ip, ip, 1
  704.     pushtos
  705.     b    ldc_more
  706.     nop;nop;nop
  707.     // 19 ldc2
  708.     lhz        r3, 0(ip)
  709.     addi    ip, ip, 2
  710.     pushtos
  711.     b    ldc_more
  712.     nop;nop;nop
  713.     // 20 ldc2w
  714.     lhz        r3, 0(ip)
  715.     addi    ip, ip, 2
  716.     pushtos
  717.     b    ldc_more
  718.     nop;nop;nop
  719.     // 21 iload
  720.     lbz        a, 0(ip)
  721.     addi    ip, ip, 1
  722.     times4(a)        // convert index to offset
  723.     pushtos
  724.     lwzx    tos, a, fp
  725.     used6
  726.     // 22 lload
  727.     used0
  728.     // 23 fload
  729.     used0
  730.     // 24 dload
  731.     used0
  732.     // 25 aload
  733.     lbz        a, 0(ip)
  734.     addi    ip, ip, 1
  735.     times4(a)        // convert index to offset
  736.     pushtos
  737.     lwzx    tos, a, fp
  738.     used6
  739.     // 26 iload_0
  740.     pushtos
  741.     lwz        tos, 0(fp)
  742.     used3
  743.     // 27 iload_1
  744.     pushtos
  745.     lwz        tos, 4(fp)
  746.     used3
  747.     // 28 iload_2
  748.     pushtos
  749.     lwz        tos, 8(fp)
  750.     used3
  751.     // 29 iload_3
  752.     pushtos
  753.     lwz        tos, 12(fp)
  754.     used3
  755.     // 30 lload_0
  756.     used0
  757.     // 31 lload_1
  758.     used0
  759.     // 32 lload_2
  760.     used0
  761.     // 33 lload_3
  762.     used0
  763.     // 34 fload_0
  764.     used0
  765.     // 35 fload_1
  766.     used0
  767.     // 36 fload_2
  768.     used0
  769.     // 37 fload_3
  770.     used0
  771.     // 38 dlload_0
  772.     used0
  773.     // 39 dload_1
  774.     used0
  775.     // 40 dload_2
  776.     used0
  777.     // 41 dload_3
  778.     used0
  779.     // 42 aload_0
  780.     pushtos
  781.     lwz        tos, 0(fp)
  782.     used3
  783.     // 43 aload_1
  784.     pushtos
  785.     lwz        tos, 4(fp)
  786.     used3
  787.     // 44 aload_2
  788.     pushtos
  789.     lwz        tos, 8(fp)
  790.     used3
  791.     // 45 aload_3
  792.     pushtos
  793.     lwz        tos, 12(fp)
  794.     used3
  795.     // 46 iaload
  796.     lwzu    b, -4(sp)    // get array address
  797.     mr        a, tos
  798.     addi    b, b, 4
  799.     times4(a)            // convert index to offset
  800.     lwzx    tos, a, b
  801.     used5
  802.     // 47 laload
  803.     lwzu    tos, -8(sp)    // drop2
  804.     used1
  805.     // 48 faload
  806.     lwzu    tos, -8(sp)    // drop2
  807.     used1
  808.     // 49 daload
  809.     lwzu    tos, -8(sp)    // drop2
  810.     used1
  811.     // 50 aaload
  812.     lwzu    b, -4(sp)    // get array address
  813.     mr        a, tos
  814.     addi    b, b, 4
  815.     times4(a)            // convert index to offset
  816.     lwzx    tos, a, b
  817.     used5
  818.     // 51 baload
  819.     lwzu    b, -4(sp)    // get array address
  820.     addi    b, b, 4
  821.     lbzx    tos, tos, b
  822.     extsb    tos, tos
  823.     used4
  824.     // 52 caload
  825.     lwzu    b, -4(sp)    // get array address
  826.     mr        a, tos
  827.     addi    b, b, 4
  828.     slwi(a, 1)            // convert index to offset
  829.     lhzx    tos, a, b
  830.     used5
  831.     // 53 saload
  832.     lwzu    b, -4(sp)    // get array address
  833.     mr        a, tos
  834.     addi    b, b, 4
  835.     slwi(a, 1)            // convert index to offset
  836.     lhax    tos, a, b
  837.     used5
  838.     // 54 istore
  839.     lbz        a, 0(ip)
  840.     addi    ip, ip, 1
  841.     times4(a)        // convert index to offset
  842.     stwx    tos, a, fp
  843.     lwzu    tos, -4(sp)
  844.     used5
  845.     // 55 lstore
  846.     used0
  847.     // 56 fstore
  848.     used0
  849.     // 57 dstore
  850.     used0
  851.     // 58 astore
  852.     lbz        a, 0(ip)
  853.     addi    ip, ip, 1
  854.     times4(a)            // convert index to offset
  855.     stwx    tos, a, fp
  856.     lwzu    tos, -4(sp)
  857.     used5
  858.     // 59 istore_0
  859.     stw        tos, 0(fp)
  860.     lwzu    tos, -4(sp)
  861.     used2
  862.     // 60 istore_1
  863.     stw        tos, 4(fp)
  864.     lwzu    tos, -4(sp)
  865.     used2
  866.     // 61 istore_2
  867.     stw        tos, 8(fp)
  868.     lwzu    tos, -4(sp)
  869.     used2
  870.     // 62 istore_3
  871.     stw        tos, 12(fp)
  872.     lwzu    tos, -4(sp)
  873.     used2
  874.     // 63 lstore_0
  875.     used0
  876.     // 64 lstore_1
  877.     used0
  878.     // 65 lstore_2
  879.     used0
  880.     // 66 lstore_3
  881.     used0
  882.     // 67 fstore_0
  883.     used0
  884.     // 68 fstore_1
  885.     used0
  886.     // 69 fstore_2
  887.     used0
  888.     // 70 fstore_3
  889.     used0
  890.     // 71 dstore_0
  891.     used0
  892.     // 72 dstore_1
  893.     used0
  894.     // 73 dstore_2
  895.     used0
  896.     // 74 dstore_3
  897.     used0
  898.     // 75 astore_0
  899.     stw        tos, 0(fp)
  900.     lwzu    tos, -4(sp)
  901.     used2
  902.     // 76 astore_1
  903.     stw        tos, 4(fp)
  904.     lwzu    tos, -4(sp)
  905.     used2
  906.     // 77 astore_2
  907.     stw        tos, 8(fp)
  908.     lwzu    tos, -4(sp)
  909.     used2
  910.     // 78 astore_3
  911.     stw        tos,12(fp)
  912.     lwzu    tos, -4(sp)
  913.     used2
  914.     // 79 iastore
  915.     lwzu    b, -4(sp)    // index
  916.     lwzu    c, -4(sp)    // array address
  917.     times4(b)            // index to offset
  918.     addi    c, c, 4        // skip arraylength field
  919.     stwx    tos, b, c
  920.     lwzu    tos, -4(sp)
  921.     used6
  922.     // 80 lastore
  923.     lwzu    tos, -8(sp)    // drop2
  924.     used1
  925.     // 81 fastore
  926.     lwzu    tos, -8(sp)    // drop2
  927.     used1
  928.     // 82 dastore
  929.     lwzu    tos, -8(sp)    // drop2
  930.     used1
  931.     // 83 aastore
  932.     lwzu    b, -4(sp)    // index
  933.     lwzu    c, -4(sp)    // array address
  934.     times4(b)            // index to offset
  935.     addi    c, c, 4        // skip arraylength field
  936.     stwx    tos, b, c
  937.     lwzu    tos, -4(sp)
  938.     used6
  939.     // 84 bastore
  940.     lwzu    b, -4(sp)    // index
  941.     lwzu    c, -4(sp)    // array address
  942.     addi    c, c, 4        // skip arraylength field
  943.     stbx    tos, b, c
  944.     lwzu    tos, -4(sp)
  945.     used5
  946.     // 85 castore
  947.     lwzu    b, -4(sp)    // index
  948.     lwzu    c, -4(sp)    // array address
  949.     slwi(b, 1)            // index to offset
  950.     addi    c, c, 4        // skip arraylength field
  951.     sthx    tos, b, c
  952.     lwzu    tos, -4(sp)
  953.     used6
  954.     // 86 sastore
  955.     lwzu    b, -4(sp)    // index
  956.     lwzu    c, -4(sp)    // array address
  957.     slwi(b, 1)            // index to offset
  958.     addi    c, c, 4        // skip arraylength field
  959.     sthx    tos, b, c
  960.     lwzu    tos, -4(sp)
  961.     used6
  962.     // 87 pop
  963.     lwzu    tos, -4(sp)
  964.     used1
  965.     // 88 pop2
  966.     lwzu    tos, -8(sp)
  967.     used1
  968.     // 89 dup
  969.     pushtos
  970.     used2
  971.     // 90 dup_x1
  972.     lwz        a, -4(sp)
  973.     stw        tos, -4(sp)
  974.     stw        a, 0(sp)
  975.     addi    sp, sp, 4
  976.     used4
  977.     // 91 dup_x2
  978.     lwz        a, -8(sp)
  979.     lwz        b, -4(sp)
  980.     stw        tos, -8(sp)
  981.     stw        a, -4(sp)
  982.     stw        b, 0(sp)
  983.     addi    sp, sp, 4
  984.     used6
  985.     // 92 dup2
  986.     lwz        a, -4(sp)
  987.     stw        tos, 0(sp)
  988.     stw        a, 4(sp)
  989.     addi    sp, sp, 8
  990.     used4
  991.     // 93 dup2_x1
  992.     lwz        a, -8(sp)
  993.     lwz        b, -4(sp)
  994.     stw        b, -8(sp)
  995.     stw        tos, -4(sp)
  996.     stw        a, 0(sp)
  997.     stw        b, 4(sp)
  998.     addi    sp, sp, 8
  999.     used7
  1000.     // 94 dup2_x2
  1001.     lwz        a, -12(sp)
  1002.     lwz        b, -8(sp)
  1003.     lwz        c, -4(sp)
  1004.     stw        c, -12(sp)
  1005.     stw        tos, -8(sp)
  1006.     stw        a, -4(sp)
  1007.     stw        b, 0(sp)
  1008.     b        dup2_x2_more
  1009.     // 95 swap
  1010.     lwz        a, -4(sp)
  1011.     stw        tos, -4(sp)
  1012.     mr        tos, a
  1013.     used3
  1014.     // 96 iadd
  1015.     lwzu    a, -4(sp)
  1016.     add        tos, a, tos
  1017.     used2
  1018.     // 97 ladd
  1019.     used6    // pretend we had 6 instructions already
  1020.     // stash the rest of dup2_x2 here
  1021. dup2_x2_more:
  1022.     stw        c, 4(sp)
  1023.     addi    sp, sp, 8
  1024.     used4
  1025.     // 98 fadd
  1026.     used0
  1027.     // 99 dadd
  1028.     used0
  1029.     // 100 isub
  1030.     lwzu    a, -4(sp)
  1031.     subf    tos, tos, a
  1032.     used2
  1033.     // 101 lsub
  1034.     used0
  1035.     // 102 fsub
  1036.     used0
  1037.     // 103 dsub
  1038.     used0
  1039.     // 104 imul
  1040.     lwzu    a, -4(sp)
  1041.     mullw    tos, tos, a
  1042.     used2
  1043.     // 105 lmul
  1044.     used0
  1045.     // 106 fmul
  1046.     used0
  1047.     // 107 dmul
  1048.     used0
  1049.     // 108 idiv
  1050.     lwzu    a, -4(sp)
  1051.     divw    tos, a, tos
  1052.     used2
  1053.     // 109 ldiv
  1054.     used0
  1055.     // 110 fdiv
  1056.     used0
  1057.     // 111 ddiv
  1058.     used0
  1059.     // 112 irem
  1060.     lwzu    a, -4(sp)
  1061.     divw    b, a, tos
  1062.     mullw    c, b, tos
  1063.     subf    tos, c, a
  1064.     used4
  1065.     // 113 lrem
  1066.     used0
  1067.     // 114 frem
  1068.     used0
  1069.     // 115 drem
  1070.     used0
  1071.     // 116 ineg
  1072.     neg        tos, tos
  1073.     used1
  1074.     // 117 lneg
  1075.     used0
  1076.     // 118 fneg
  1077.     used0
  1078.     // 119 dneg
  1079.     used0
  1080.     // 120 ishl
  1081.     lwzu    a, -4(sp)
  1082.     andi.    tos, tos, 31
  1083.     slw        tos, a, tos
  1084.     used3
  1085.     // 121 lshl
  1086.     lwzu    tos, -4(sp)
  1087.     used1
  1088.     // 122 ishr
  1089.     lwzu    a, -4(sp)
  1090.     andi.    tos, tos, 31
  1091.     sraw    tos, a, tos
  1092.     used3
  1093.     // 123 lshr
  1094.     lwzu    tos, -4(sp)
  1095.     used1
  1096.     // 124 iushr
  1097.     lwzu    a, -4(sp)
  1098.     andi.    tos, tos, 31
  1099.     srw        tos, a, tos
  1100.     used3
  1101.     // 125 lushr
  1102.     lwzu    tos, -4(sp)
  1103.     used1
  1104.     // 126 iand
  1105.     lwzu    a, -4(sp)
  1106.     and        tos, tos, a
  1107.     used2
  1108.     // 127 land
  1109.     used0
  1110.     // 128 ior
  1111.     lwzu    a, -4(sp)
  1112.     or        tos, tos, a
  1113.     used2
  1114.     // 129 lor
  1115.     used0
  1116.     // 130 ixor
  1117.     lwzu    a, -4(sp)
  1118.     xor        tos, tos, a
  1119.     used2
  1120.     // 131 lxor
  1121.     used0
  1122.     // 132 iinc
  1123.     lhz        b, 0(ip)
  1124.     rlwinm    a, b, 26, 16, 29
  1125.     extsb    b, b
  1126.     addi    ip, ip, 2
  1127.     lwzx    c, fp, a
  1128.     add        c, c, b
  1129.     stwx    c, fp, a
  1130.     used7
  1131.     // 133 i2l
  1132.     lwzu    tos, -4(sp)
  1133.     used1
  1134.     // 134 i2f
  1135.     lwzu    tos, -4(sp)
  1136.     used1
  1137.     // 135 i2d
  1138.     lwzu    tos, -4(sp)
  1139.     used1
  1140.     // 136 l2i
  1141.     pushi(0)
  1142.     used3
  1143.     // 137 l2f
  1144.     used0
  1145.     // 138 l2d
  1146.     used0
  1147.     // 139 f2i
  1148.     pushi(0)
  1149.     used3
  1150.     // 140 f2f
  1151.     used0
  1152.     // 141 f2d
  1153.     used0
  1154.     // 142 d2i
  1155.     pushi(0)
  1156.     used3
  1157.     // 143 d2f
  1158.     used0
  1159.     // 144 d2d
  1160.     used0
  1161.     // 145 int2byte
  1162.     extsb    tos, tos
  1163.     used1
  1164.     // 146 int2char
  1165.     andi.    tos, tos, 0xffff
  1166.     used1
  1167.     // 147 int2short
  1168.     extsh    tos, tos
  1169.     used1
  1170.     // 148 lcmp
  1171.     pushi(0)
  1172.     used3
  1173.     // 149 fcmpl
  1174.     pushi(0)
  1175.     used3
  1176.     // 150 fcmpg
  1177.     pushi(0)
  1178.     used3
  1179.     // 151 dcmpl
  1180.     pushi(0)
  1181.     used3
  1182.     // 152 dcmpg
  1183.     pushi(0)
  1184.     used3
  1185.     // 153 ifeq
  1186.     cmpi    cr0, 0, tos, 0
  1187.     lha        a, 0(ip)
  1188.     lwzu    tos, -4(sp)
  1189.     addi    ip, ip, 2
  1190.     subi    a, a, 3
  1191.     bne        next0
  1192.     add        ip, ip, a
  1193.     used7
  1194.     // 154 ifne
  1195.     cmpi    cr0, 0, tos, 0
  1196.     lha        a, 0(ip)
  1197.     lwzu    tos, -4(sp)
  1198.     addi    ip, ip, 2
  1199.     subi    a, a, 3
  1200.     beq        next0
  1201.     add        ip, ip, a
  1202.     used7
  1203.     // 155 iflt
  1204.     cmpi    cr0, 0, tos, 0
  1205.     lha        a, 0(ip)
  1206.     lwzu    tos, -4(sp)
  1207.     addi    ip, ip, 2
  1208.     subi    a, a, 3
  1209.     bge        next0
  1210.     add        ip, ip, a
  1211.     used7
  1212.     // 156 ifge
  1213.     cmpi    cr0, 0, tos, 0
  1214.     lha        a, 0(ip)
  1215.     lwzu    tos, -4(sp)
  1216.     addi    ip, ip, 2
  1217.     subi    a, a, 3
  1218.     blt        next0
  1219.     add        ip, ip, a
  1220.     used7
  1221.     // 157 ifgt
  1222.     cmpi    cr0, 0, tos, 0
  1223.     lha        a, 0(ip)
  1224.     lwzu    tos, -4(sp)
  1225.     addi    ip, ip, 2
  1226.     subi    a, a, 3
  1227.     ble        next0
  1228.     add        ip, ip, a
  1229.     used7
  1230.     // 158 ifle
  1231.     cmpi    cr0, 0, tos, 0
  1232.     lha        a, 0(ip)
  1233.     lwzu    tos, -4(sp)
  1234.     addi    ip, ip, 2
  1235.     bgt        next0
  1236. do_jump:    // shared by cmp instructions
  1237.     subi    a, a, 3
  1238.     add        ip, ip, a
  1239.     used7
  1240.     // 159 if_icmpeq
  1241.     lwz        b, -4(sp)
  1242.     cmp        cr0, 0, b, tos
  1243.     lha        a, 0(ip)
  1244.     lwzu    tos, -8(sp)
  1245.     addi    ip, ip, 2
  1246.     beq        do_jump
  1247.     used6
  1248.     // 160 if_icmpne
  1249.     lwz        b, -4(sp)
  1250.     cmp        cr0, 0, b, tos
  1251.     lha        a, 0(ip)
  1252.     lwzu    tos, -8(sp)
  1253.     addi    ip, ip, 2
  1254.     bne        do_jump
  1255.     used6
  1256.     // 161 if_icmplt
  1257.     lwz        b, -4(sp)
  1258.     cmp        cr0, 0, b, tos
  1259.     lha        a, 0(ip)
  1260.     lwzu    tos, -8(sp)
  1261.     addi    ip, ip, 2
  1262.     blt        do_jump
  1263.     used6
  1264.     // 162 if_icmpge
  1265.     lwz        b, -4(sp)
  1266.     cmp        cr0, 0, b, tos
  1267.     lha        a, 0(ip)
  1268.     lwzu    tos, -8(sp)
  1269.     addi    ip, ip, 2
  1270.     bge        do_jump
  1271.     used6
  1272.     // 163 if_icmpgt
  1273.     lwz        b, -4(sp)
  1274.     cmp        cr0, 0, b, tos
  1275.     lha        a, 0(ip)
  1276.     lwzu    tos, -8(sp)
  1277.     addi    ip, ip, 2
  1278.     bgt        do_jump
  1279.     used6
  1280.     // 164 if_icmple
  1281.     lwz        b, -4(sp)
  1282.     cmp        cr0, 0, b, tos
  1283.     lha        a, 0(ip)
  1284.     lwzu    tos, -8(sp)
  1285.     addi    ip, ip, 2
  1286.     ble        do_jump
  1287.     used6
  1288.     // 165 if_acmpeq
  1289.     lwz        b, -4(sp)
  1290.     cmp        cr0, 0, b, tos
  1291.     lha        a, 0(ip)
  1292.     lwzu    tos, -8(sp)
  1293.     addi    ip, ip, 2
  1294.     beq        do_jump
  1295.     used6
  1296.     // 166 if_acmpne
  1297.     lwz        b, -4(sp)
  1298.     cmp        cr0, 0, b, tos
  1299.     lha        a, 0(ip)
  1300.     lwzu    tos, -8(sp)
  1301.     addi    ip, ip, 2
  1302.     bne        do_jump
  1303.     used6
  1304.     // 167 goto
  1305.     lha        a, 0(ip)
  1306.     subi        ip, ip, 1
  1307.     add        ip, ip, a
  1308.     used3
  1309.     // 168 jsr
  1310.     pushtos
  1311.     lha        a, 0(ip)
  1312.     addi    tos, ip, 2    // addr of next instr
  1313.     subi    ip, ip, 1
  1314.     add        ip, ip, a
  1315.     used6
  1316.     // 169 ret
  1317.     lbz        a, 0(ip)
  1318.     times4(a)            // convert to offset
  1319.     lwzx    ip, fp, a
  1320.     used3
  1321.     // 170 tableswitch
  1322.     mr        r3, ip
  1323.     mr        r4, tsBase
  1324.     mr        r5, tos
  1325.     bl        TableSwitch
  1326.     mr        ip, r3
  1327.     poptos
  1328.     used6
  1329.     // 171 lookupswitch
  1330.     mr        r3, ip
  1331.     mr        r4, tsBase
  1332.     mr        r5, tos
  1333.     bl        LookupSwitch
  1334.     mr        ip, r3
  1335.     poptos
  1336.     used6
  1337.     // 172 ireturn
  1338.     lwz        ip, 8(rp)
  1339.     mr        sp, fp
  1340.     lwz        fp, 4(rp)
  1341.     lwz        tsBase, 0(rp)
  1342.     addi    rp, rp, 12
  1343.     used5
  1344.     // 173 lreturn
  1345.     lwz        ip, 8(rp)
  1346.     mr        sp, fp
  1347.     lwz        fp, 4(rp)
  1348.     lwz        tsBase, 0(rp)
  1349.     lwzu    tos, -4(sp)
  1350.     addi    rp, rp, 12
  1351.     used6
  1352.     // 174 freturn
  1353.     lwz        ip, 8(rp)
  1354.     mr        sp, fp
  1355.     lwz        fp, 4(rp)
  1356.     lwz        tsBase, 0(rp)
  1357.     lwzu    tos, -4(sp)
  1358.     addi    rp, rp, 12
  1359.     used6
  1360.     // 175 dreturn
  1361.     lwz        ip, 8(rp)
  1362.     mr        sp, fp
  1363.     lwz        fp, 4(rp)
  1364.     lwz        tsBase, 0(rp)
  1365.     lwzu    tos, -4(sp)
  1366.     addi    rp, rp, 12
  1367.     used6
  1368.     // 176 areturn
  1369.     lwz        ip, 8(rp)
  1370.     mr        sp, fp
  1371.     lwz        fp, 4(rp)
  1372.     lwz        tsBase, 0(rp)
  1373.     addi    rp, rp, 12
  1374.     used5
  1375.     // 177 return
  1376.     lwz        ip, 8(rp)
  1377.     mr        sp, fp
  1378.     lwz        fp, 4(rp)
  1379.     lwz        tsBase, 0(rp)
  1380.     lwzu    tos, -4(sp)
  1381.     addi    rp, rp, 12
  1382.     used6
  1383.     // 178 getstatic
  1384.     lhz        a, 0(ip)
  1385.     addi    ip, ip, 2
  1386.     times4(a)
  1387.     lwzx    b, cp, a
  1388.     b        getstatic_more
  1389.     nop;nop;nop
  1390.     // 179 putstatic
  1391.     lhz        a, 0(ip)
  1392.     addi    ip, ip, 2
  1393.     times4(a)
  1394.     lwzx    b, cp, a
  1395.     b        putstatic_more
  1396.     nop;nop;nop
  1397.     // 180 getfield
  1398.     lhz        a, 0(ip)
  1399.     addi    ip, ip, 2
  1400.     times4(a)
  1401.     lwzx    b, cp, a
  1402.     b        getfield_more
  1403.     nop;nop;nop
  1404.     // 181 putfield
  1405.     lhz        a, 0(ip)
  1406.     addi    ip, ip, 2
  1407.     times4(a)
  1408.     lwzx    b, cp, a
  1409.     b        putfield_more
  1410.     nop;nop;nop
  1411.     // 182 invokevirtual
  1412.     lhz        a, 0(ip)
  1413.     addi    ip, ip, 2
  1414.     times4(a)            // convert to index
  1415.     lwzx    a, cp, a
  1416.     lwz        methodP, 1(a)
  1417.     stwu    ip, -4(rp)
  1418.     b        start_method
  1419.     nop
  1420.     // 183 invokenonvirtual
  1421.     lhz        a, 0(ip)
  1422.     addi    ip, ip, 2
  1423.     times4(a)            // convert to index
  1424.     lwzx    a, cp, a
  1425.     lwz        methodP, 1(a)
  1426.     stwu    ip, -4(rp)
  1427.     b        start_method
  1428.     nop
  1429.     // 184 invokestatic
  1430.     lhz        a, 0(ip)
  1431.     addi    ip, ip, 2
  1432.     times4(a)            // convert to index
  1433.     lwzx    a, cp, a
  1434.     lwz        methodP, 1(a)
  1435.     stwu    ip, -4(rp)
  1436.     b        start_method
  1437.     nop
  1438.     // 185 invokeinterface
  1439.     addi    ip, ip, 2
  1440.     used1
  1441.     // 186 undefined
  1442.     used0
  1443.     // 187 new
  1444.     addi    ip, ip, 2
  1445.     used1
  1446.     // 188 newarray
  1447.     lbz        r3, 0(ip)
  1448.     addi    ip, ip, 1
  1449.     mr        r4, tos
  1450.     bl        GetNewArray
  1451.     mr        tos, r3
  1452.     used5
  1453.     // 189 anewarray
  1454.     addi    ip, ip, 2    // skip type
  1455.     mr        r3, tos
  1456.     bl        GetANewArray
  1457.     mr        tos, r3
  1458.     used4
  1459.     // 190 arraylength
  1460.     lwz        tos, 0(tos)
  1461.     used1
  1462.     // 191 athrow
  1463.     used0
  1464.     // 192 checkcast
  1465.     addi    ip, ip, 2
  1466.     used1
  1467.     // 193 instanceof
  1468.     addi    ip, ip, 2
  1469.     li        tos, 1        // assume true
  1470.     used2
  1471.     // 194 monitorenter
  1472.     poptos
  1473.     used1
  1474.     // 195 monitorexit
  1475.     poptos
  1476.     used1
  1477.     // 196 wide
  1478.     addi    ip, ip, 1
  1479.     used1
  1480.     // 197 multianewarray
  1481.     lhz        r3, 0(ip)
  1482.     lbz        r4, 2(ip)
  1483.     addi    ip, ip, 3
  1484.     pushtos
  1485.     b        multianewarray_more
  1486.     nop;nop;
  1487.     // 198 ifnull
  1488.     cmpi    cr0, 0, tos, 0
  1489.     lha        a, 0(ip)
  1490.     lwzu    tos, -4(sp)
  1491.     addi    ip, ip, 2
  1492.     subi    a, a, 3
  1493.     bne        next0
  1494.     add        ip, ip, a
  1495.     used7
  1496.     // 199 ifnonnull
  1497.     cmpi    cr0, 0, tos, 0
  1498.     lha        a, 0(ip)
  1499.     lwzu    tos, -4(sp)
  1500.     addi    ip, ip, 2
  1501.     subi    a, a, 3
  1502.     beq        next0
  1503.     add        ip, ip, a
  1504.     used7
  1505.     // 200 goto_w
  1506.     lwz        a, 0(ip)
  1507.     subi    a, a, 1
  1508.     add        ip, ip, a
  1509.     used3
  1510.     // 201 jsr_w
  1511.     pushtos
  1512.     lwz        a, 0(ip)
  1513.     addi    tos, ip, 5
  1514.     subi    a, a, 1
  1515.     add        ip, ip, a
  1516.     used6
  1517.     // 202 breakpoint
  1518.     used0
  1519.     // 203 unused - but we use it to signal final exit
  1520.     b    exitVM
  1521.     used1
  1522.     used0    // 204
  1523.     used0    // 205
  1524.     used0    // 206
  1525.     used0    // 207
  1526.     used0    // 208
  1527.     // 209 ret_w
  1528.     lhz        a, 0(ip)
  1529.     times4(a)
  1530.     lwzx    ip, fp, a
  1531.     used3
  1532.  
  1533.     // remaining opcodes unused
  1534.     
  1535. exitVM:
  1536.     mr        r3, tos    
  1537.     frfree
  1538.     blr
  1539.  
  1540. ldc_more:
  1541.     stw        sp, SP
  1542.     bl        PushConstant
  1543.     lwz        sp, SP
  1544.     poptos
  1545.     b        next0
  1546.     
  1547. multianewarray_more:
  1548.     stw        sp, SP
  1549.     bl        PushMultiANewArray
  1550.     lwz        sp, SP
  1551.     poptos
  1552.     b        next0
  1553.  
  1554. getstatic_more:
  1555.     lwz        a, 1(b)        // get fieldP
  1556.     lwz        b, 8(a)        // get size
  1557.     cmpi    cr0, 0, b, 0
  1558.     lwz        c, 4(a)        // get offset
  1559.     beq        next0
  1560.     pushtos
  1561.     lwzx    tos, h0, c
  1562.     b        next0
  1563.     
  1564. putstatic_more:
  1565.     lwz        a, 1(b)        // get fieldP
  1566.     lwz        b, 8(a)        // get size
  1567.     cmpi    cr0, 0, b, 0
  1568.     lwz        c, 4(a)        // get offset
  1569.     beq        drop1ngo
  1570.     stwx    tos, h0, c
  1571.     poptos
  1572.     b        next0
  1573.     
  1574. getfield_more:
  1575.     lwz        a, 1(b)        // get fieldP
  1576.     lwz        b, 8(a)        // get size
  1577.     cmpi    cr0, 0, b, 0
  1578.     lwz        c, 4(a)        // get offset
  1579.     beq        drop1ngo
  1580.     lwzx    tos, tos, c
  1581.     b        next0
  1582.     
  1583. putfield_more:
  1584.     lwz        a, 1(b)        // get fieldP
  1585.     lwz        b, 8(a)        // get size
  1586.     cmpi    cr0, 0, b, 0
  1587.     lwz        c, 4(a)        // get offset
  1588.     beq        drop2ngo
  1589.     lwzu    a, -4(sp)
  1590.     stwx    tos, a, c
  1591.     poptos
  1592.     b        next0
  1593.  
  1594. drop2ngo:
  1595.     poptos
  1596. drop1ngo:
  1597.     poptos
  1598.     b        next0
  1599.     
  1600. }
  1601.  
  1602.  
  1603. static void PushConstant(long n)
  1604. {
  1605.     u1        *p;
  1606.     
  1607.     p = Constants[n];
  1608.     switch (*p++)
  1609.     {
  1610.         case C_Utf8:
  1611.         case C_Unicode:
  1612.             // since no operations act on these objects,
  1613.             // I just make the const data be the object
  1614.             // (w/o the tag) for simplicity of the test code.
  1615.             PUSH((long)p);
  1616.             break;
  1617.         case C_Integer:    PUSH(*(s4*)p); break;
  1618.         case C_Float:    break;
  1619.         case C_Long:    break;
  1620.         case C_Double:    break;
  1621.         case C_Class:    break;
  1622.         case C_String:    PushConstant(*(u2*)p); break;
  1623.         case C_Fieldref:
  1624.         case C_Methodref:
  1625.         case C_InterfaceMethodref:
  1626.         case C_NameAndType:    DebugStr("\pit can happen"); break;
  1627.     }
  1628. }
  1629.  
  1630.  
  1631. static u1 *TableSwitch(u1 *ip, long tsBase, long n)
  1632. {
  1633.     long    *base;
  1634.     long    defaultOffset;
  1635.     long    low;
  1636.     long    high;
  1637.     
  1638.     base = (long *) (((((long)ip-tsBase) + 3) & -4)+tsBase);
  1639.     defaultOffset = *base++;
  1640.     low = *base++;
  1641.     high = *base++;
  1642.     ip -= 1;
  1643.     
  1644.     if (n < low || n > high)
  1645.         ip += defaultOffset;
  1646.     else
  1647.         ip += base[n - low];
  1648.     return ip;
  1649. }
  1650.  
  1651.  
  1652. static u1 *LookupSwitch(u1 *ip, long tsBase, long key)
  1653. {
  1654.     long    *base;
  1655.     long    defaultOffset;
  1656.     long    numPairs;
  1657.     long    match;
  1658.     
  1659.     base = (long *) (((((long)ip-tsBase) + 3) & -4)+tsBase);
  1660.     defaultOffset = *base++;
  1661.     numPairs = *base++;
  1662.     ip -= 1;
  1663.     
  1664.     while (numPairs > 0)
  1665.     {
  1666.         match = *base++;
  1667.         numPairs -= 1;
  1668.         if (key == match)
  1669.             return ip + *base;
  1670.         base += 1;
  1671.     }
  1672.     return ip + defaultOffset;
  1673. }
  1674.  
  1675.  
  1676. // Array object: # elements, data
  1677. // data is padded to multiple of 4
  1678. static long GetNewArray(long type, long size)
  1679. {
  1680.     long        result;
  1681.     long        elementSize;
  1682.     
  1683.     result = (long) HP;
  1684.     *HP++ = size;
  1685.     if (type == 10)                // int
  1686.         elementSize = 4;
  1687.     else if ((type & 3) == 0)    // boolean or byte
  1688.         elementSize = 1;
  1689.     else if ((type & 3) == 1)    // char or short
  1690.         elementSize = 2;
  1691.     else
  1692.         elementSize = 0;        // unsupported types
  1693.     HP += ((size * elementSize + 3) >> 2);
  1694.     return result;
  1695. }
  1696.  
  1697.  
  1698. static long GetANewArray(long size)
  1699. {
  1700.     long        result;
  1701.     long        elementSize;
  1702.     u4            *objectP;
  1703.     
  1704.     result = (long) HP;
  1705.     *HP++ = size;
  1706.     elementSize = 4;
  1707.     objectP = (u4*) HP;
  1708.     HP = (long *) ((u1 *) HP + size * 4);
  1709.     while (size > 0)
  1710.     {
  1711.         size -= 1;
  1712.         *objectP = (u4)HP;
  1713.         HP += elementSize;
  1714.     }
  1715.     return result;
  1716. }
  1717.  
  1718.  
  1719. // Rather complicated function to allocate a
  1720. // multi-dimensional array as arrays of array objects.
  1721. static void PushMultiANewArray(long classIndex,
  1722.                                 long numDimensions)
  1723. {
  1724.     u1        *cp;
  1725.     long    nameIndex;
  1726.     u1        *name;
  1727.     int        type;
  1728.     long    elementSize;
  1729.     long    arrayRef;
  1730.     long    size;
  1731.     long    copies;
  1732.     long    i, j;
  1733.     long    dim;
  1734.     long    dataLongs;
  1735.     long    *subArrayRef;
  1736.     long    subArrayLongs;
  1737.     
  1738.     arrayRef = (long) HP;
  1739.     cp = Constants[classIndex];
  1740.     nameIndex = *(u2*) (cp+1);
  1741.     cp = Constants[nameIndex];
  1742.     name = cp + 3;
  1743.     type = name[numDimensions];    // skip the known '[' chars
  1744.     if (type == 'I' || type == '[')            // int or ref
  1745.         elementSize = 4;
  1746.     else if (type == 'Z' || type == 'B')    // bool or byte
  1747.         elementSize = 1;
  1748.     else if (type == 'C' || type == 'S')    // char or short
  1749.         elementSize = 2;
  1750.     else
  1751.         elementSize = 0;        // unsupported types
  1752.     copies = 1;
  1753.  
  1754.     size = *(SP-1);    // the nth dimension
  1755.     dataLongs = (size * elementSize + 3) >> 2;
  1756.     for (dim = 0; dim < numDimensions - 1; dim++)
  1757.     {
  1758.         size = *(SP-numDimensions+dim);
  1759.         if (dim == numDimensions - 2)
  1760.             subArrayLongs = dataLongs + 1;
  1761.         else
  1762.             subArrayLongs = *(SP-numDimensions+dim+1) + 1;
  1763.         subArrayRef = HP + (size + 1) * copies;
  1764.         for (i = 0; i < copies; i++)
  1765.         {
  1766.             *HP++ = size;
  1767.             for (j = 0; j < size; j++)
  1768.             {
  1769.                 *HP++ = (long) subArrayRef;
  1770.                 subArrayRef += subArrayLongs;
  1771.             }
  1772.         }
  1773.         copies *= size;
  1774.     }
  1775.     // last dim is special since it has no subarrays
  1776.     size = *(SP-1);    // the nth dimension
  1777.     for (i = 0; i < copies; i++)
  1778.     {
  1779.         *HP++ = size;
  1780.         HP += dataLongs;
  1781.     }
  1782.     SP -= numDimensions;    // remove dimensions
  1783.     PUSH(arrayRef);
  1784. }
  1785.  
  1786.  
  1787.  
  1788.  
  1789.  
  1790.  
  1791.  
  1792.  
  1793.  
  1794.